﻿using Common;
using Ivi.Visa.FormattedIO;
using Ivi.Visa;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NewDevice.USB
{
    /// <summary>
    /// SCPI (Standard Commands for Programmable Instruments) 通信基础类
    /// 提供基于 VISA 标准的仪器通信基础功能
    /// </summary>
    public class SCPIBase : IDisposable
    {
        private IMessageBasedSession session = null;
        private MessageBasedFormattedIO formattedIO;

        /// <summary>
        /// 设备名
        /// </summary>
        protected string deviceName = "";

        /// <summary>
        /// 初始化设备名
        /// </summary>
        /// <param name="devName"></param>
        public SCPIBase(string devName = "VISA设备")
        {
            deviceName = devName;
        }

        /// <summary>
        /// 连接到指定的 VISA 地址
        /// </summary>
        /// <param name="visaAddress">VISA 资源地址 (如 "TCPIP0::192.168.1.100::inst0::INSTR")</param>
        /// <exception cref="InvalidOperationException">当会话打开失败时抛出</exception>
        /// <exception cref="Exception">当发生其他连接错误时抛出</exception>
        /// <example>
        /// <code>
        /// var scpi = new SCPIBase();
        /// scpi.Connect("TCPIP0::192.168.1.100::inst0::INSTR");
        /// </code>
        /// </example>
        public void Connect(string visaAddress)
        {
            try
            {
                session = GlobalResourceManager.Open(visaAddress) as IMessageBasedSession;

                if (session == null)
                {
                    throw new InvalidOperationException("Failed to open a session. Please check the VISA address.");
                }

                formattedIO = new MessageBasedFormattedIO(session);

                // For Serial and TCP/IP socket connections enable the read
                // Termination Character
                if (session.ResourceName.Contains("ASRL") || session.ResourceName.Contains("SOCKET"))
                {
                    session.TerminationCharacterEnabled = true;
                }

                Mylog.Debug($"VISA设备[{deviceName}]已连接");
            }
            catch (NativeVisaException visaEx)
            {
                throw new Exception($"VISA exception occurred: {visaEx.Message}");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 发送 SCPI 命令到设备 (无响应)
        /// </summary>
        /// <param name="cmd">要发送的 SCPI 命令字符串</param>
        /// <remarks>
        /// 此方法会自动清空输入/输出缓冲区后再发送命令
        /// </remarks>
        public void SendCmd(string cmd)
        {
            formattedIO.DiscardBuffers();
            Mylog.Debug($"{deviceName} SendCmd:[{cmd}]");
            formattedIO.WriteLine(cmd);
        }

        /// <summary>
        /// 从设备读取响应
        /// </summary>
        /// <returns>设备返回的响应字符串 (自动去除结尾的换行符)</returns>
        /// <remarks>
        /// 通常用于在调用 SendCmd 后读取设备响应
        /// </remarks>
        public string ReadResponse()
        {
            var ret = formattedIO.ReadLine().TrimEnd('\n');
            Mylog.Debug($"{deviceName} ResponseCmd:[{ret}]");
            return ret;
        }

        /// <summary>
        /// 发送查询命令并获取响应 (原子操作)
        /// </summary>
        /// <param name="cmd">要发送的 SCPI 查询命令 (通常以?结尾)</param>
        /// <returns>设备返回的响应字符串 (自动去除结尾的换行符)</returns>
        /// <remarks>
        /// 此方法会自动:
        /// 1. 清空输入/输出缓冲区
        /// 2. 发送查询命令
        /// 3. 读取响应
        /// </remarks>
        /// <example>
        /// <code>
        /// string idn = scpi.Query("*IDN?");
        /// </code>
        /// </example>
        public string Query(string cmd)
        {
            Mylog.Debug($"{deviceName} QuerySendCmd:[{cmd}]");
            formattedIO.DiscardBuffers();
            formattedIO.WriteLine(cmd);
            var ret = formattedIO.ReadLine().TrimEnd('\n');
            Mylog.Debug($"{deviceName} ResponseCmd:[{ret}]");
            return ret;
        }

        /// <summary>
        /// 释放资源并关闭 VISA 会话
        /// </summary>
        /// <remarks>
        /// 实现 IDisposable 接口，建议使用 using 语句或手动调用 Dispose
        /// </remarks>
        public void Dispose()
        {
            if (session != null)
            {
                session.Dispose();
                session = null;
                Mylog.Debug($"VISA设备[{deviceName}]已断开连接");
            }
        }
    }
}